package com.kotlin.dongdong.framework.ormlite

import android.content.Context
import com.j256.ormlite.dao.Dao
import com.kotlin.dongdong.demo.entity.UserEntity
import com.kotlin.dongdong.framework.base.BaseAppConlication
import com.kotlin.dongdong.framework.ormlite.base.DBBaseEntity
import java.lang.Exception
import java.sql.SQLException
import java.util.ArrayList
import java.util.HashMap
import java.util.concurrent.Callable

/**
 * Created by dongdong on 2018/2/1.
 */
class DBManager {

    var dbhelper: DBHelper? = null
    var context: Context? = null

    public fun DBManager() {
        context = BaseAppConlication.appContext!!
    }

    private object Instance {
        var dbmanager = DBManager()
    }

    companion object {

        val DB_NAME: String = "dongdong.db"
        val DB_VERSION: Int = 1
        val DB_CODE_FAIL = -1

        fun get(): DBManager {

            return Instance.dbmanager
        }

        fun initDB() {

            DBHelper.initDB(BaseAppConlication.appContext!!, DB_NAME, DB_VERSION, getDBTables())
            DBHelper.helper
        }


        fun getDBTables(): List<Class<*>> {
            var tables = ArrayList<Class<*>>()
            tables.add(UserEntity::class.java)
            return tables
        }

    }


    public fun saveOrUpdate(entity: DBBaseEntity): Int {

        var clz: Class<DBBaseEntity> = entity.javaClass
        try {
            var dao = getDao(clz)
            var status = dao!!.createOrUpdate(entity)
            var result = 0
            if (status.isCreated) {
                result = 1
            }
            if (status.isUpdated) {
                result = 2
            }
            return result

        } catch (e: SQLException) {
            return DB_CODE_FAIL
        }

    }


    public fun saveOrUpdate(entityes: List<DBBaseEntity>): Boolean {

        if (null == entityes || entityes.size == 0) {
            return false
        }
        try {
            val entity = entityes[0]
            val clz = entity.javaClass
            val dao = getDao(clz)

            dao!!.callBatchTasks(Callable<Void> {
                for (entity in entityes) {
                    dao!!.createOrUpdate(entity)
                }
                null
            })

        } catch (e: SQLException) {
            return false
        }
        return true
    }

    fun delete(entity: DBBaseEntity): Int {
        try {
            val clz = entity.javaClass
            val dao = getDao(clz)
            return dao!!.delete(entity)
        } catch (e: SQLException) {
            return DB_CODE_FAIL
        }
    }

    fun <T : DBBaseEntity, D : Any?> deleteById(clz: Class<T>, id: D): Int {
        try {
            val dao = getDaoById(clz)
            return dao!!.deleteById(id)
        } catch (e: SQLException) {
            e.printStackTrace()
            return DB_CODE_FAIL
        }
    }

    fun delete(entityes: List<DBBaseEntity>): Int {

        try {
            val entity = entityes[0]
            val clz = entity.javaClass
            val dao = getDao(clz)
            dao!!.callBatchTasks(Callable<Void> {
                for (entity in entityes) {
                    dao!!.delete(entity)
                }
                null
            })
        } catch (e: Exception) {
            e.printStackTrace()
            return DB_CODE_FAIL
        }

        return 0
    }


    fun <T : DBBaseEntity> queryForAll(entityType: Class<T>): List<T>? {
        try {
            return DBHelper.helper!!.getDao(entityType).queryForAll()
        } catch (e: SQLException) {
            e.printStackTrace()
        }

        return null
    }

    fun <T : DBBaseEntity> queryForId(entityType: Class<T>, idValue: Any): T? {
        try {
            val dao = getDaoById(entityType)
            return dao!!.queryForId(idValue) as T
        } catch (e: SQLException) {
            e.printStackTrace()
        }
        return null
    }

    fun <T : DBBaseEntity> queryForEq(entityType: Class<T>, fieldName: String, value: Any): List<T>? {

        val map = HashMap<String, Any>()
        map.put(fieldName, value)
        return queryForFieldValues(entityType, map)
    }

    fun <T : DBBaseEntity> queryForFieldValues(entityType: Class<T>,
                                               fieldValues: Map<String, Any>?): List<T>? {
        var fieldValues = fieldValues

        if (null == fieldValues) {
            fieldValues = HashMap()
        }
        try {
            val dao = getDao(entityType)
            return dao!!.queryForFieldValues(fieldValues) as List<T>
        } catch (e: SQLException) {
            e.printStackTrace()
        }

        return null
    }


    fun <D : Dao<T, *>, T> getDao(clazz: Class<T>): D? {
        try {
            return DBHelper.helper!!.getDao(clazz)
        } catch (e: SQLException) {
            e.printStackTrace()
        }

        return null
    }

    fun <D : Dao<T, Any>, T> getDaoById(clazz: Class<T>): D? {
        try {
            return DBHelper.helper!!.getDao(clazz)
        } catch (e: SQLException) {
            e.printStackTrace()
        }

        return null
    }
}